//! 调度器指标收集
//! 
//! 提供调度器性能监控和指标收集功能

use std::sync::Arc;
use std::time::{Duration, Instant};
use std::collections::HashMap;
use tokio::sync::RwLock;
use serde::{Serialize, Deserialize};
use anyhow::Result;
use tracing::info;

/// 调度器指标收集器
pub struct SchedulerMetrics {
    /// 总请求数
    total_requests: Arc<RwLock<u64>>,
    /// 成功调度数
    successful_schedulings: Arc<RwLock<u64>>,
    /// 失败调度数
    failed_schedulings: Arc<RwLock<u64>>,
    /// 调度时间样本
    scheduling_times: Arc<RwLock<Vec<Duration>>>,
    /// 按池类型统计的分配次数
    pool_allocations: Arc<RwLock<HashMap<String, u64>>>,
    /// 按优先级统计的请求次数
    priority_stats: Arc<RwLock<HashMap<String, u64>>>,
    /// 按语言统计的请求次数
    language_stats: Arc<RwLock<HashMap<String, u64>>>,
    /// 队列等待时间样本
    queue_wait_times: Arc<RwLock<Vec<Duration>>>,
    /// 策略使用统计
    policy_usage: Arc<RwLock<HashMap<String, PolicyUsageStats>>>,
    /// 启动时间
    start_time: Instant,
}

/// 策略使用统计
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyUsageStats {
    /// 使用次数
    pub usage_count: u64,
    /// 成功次数
    pub success_count: u64,
    /// 平均决策时间
    pub avg_decision_time: Duration,
    /// 置信度分布
    pub confidence_distribution: Vec<f64>,
}

impl Default for PolicyUsageStats {
    fn default() -> Self {
        Self {
            usage_count: 0,
            success_count: 0,
            avg_decision_time: Duration::from_millis(0),
            confidence_distribution: Vec::new(),
        }
    }
}

/// 指标快照
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchedulerMetricsSnapshot {
    /// 总请求数
    pub total_requests: u64,
    /// 成功调度数
    pub successful_schedulings: u64,
    /// 失败调度数
    pub failed_schedulings: u64,
    /// 成功率
    pub success_rate: f64,
    /// 平均调度时间
    pub average_scheduling_time: Duration,
    /// 中位数调度时间
    pub median_scheduling_time: Duration,
    /// 99分位数调度时间
    pub p99_scheduling_time: Duration,
    /// 按池类型的分配统计
    pub pool_allocations: HashMap<String, u64>,
    /// 按优先级的请求统计
    pub priority_stats: HashMap<String, u64>,
    /// 按语言的请求统计
    pub language_stats: HashMap<String, u64>,
    /// 平均队列等待时间
    pub average_queue_wait_time: Duration,
    /// 策略使用统计
    pub policy_usage: HashMap<String, PolicyUsageStats>,
    /// 运行时间
    pub uptime: Duration,
    /// 吞吐量（每秒请求数）
    pub throughput: f64,
}

impl SchedulerMetrics {
    /// 创建新的指标收集器
    pub fn new() -> Self {
        Self {
            total_requests: Arc::new(RwLock::new(0)),
            successful_schedulings: Arc::new(RwLock::new(0)),
            failed_schedulings: Arc::new(RwLock::new(0)),
            scheduling_times: Arc::new(RwLock::new(Vec::new())),
            pool_allocations: Arc::new(RwLock::new(HashMap::new())),
            priority_stats: Arc::new(RwLock::new(HashMap::new())),
            language_stats: Arc::new(RwLock::new(HashMap::new())),
            queue_wait_times: Arc::new(RwLock::new(Vec::new())),
            policy_usage: Arc::new(RwLock::new(HashMap::new())),
            start_time: Instant::now(),
        }
    }

    /// 启动指标收集
    pub async fn start(&self) -> Result<()> {
        info!("启动调度器指标收集");
        Ok(())
    }

    /// 停止指标收集
    pub async fn stop(&self) -> Result<()> {
        info!("停止调度器指标收集");
        Ok(())
    }

    /// 增加提交的请求数
    pub async fn increment_submitted_requests(&self) {
        let mut total = self.total_requests.write().await;
        *total += 1;
    }

    /// 增加成功调度数
    pub async fn increment_successful_schedulings(&self) {
        let mut successful = self.successful_schedulings.write().await;
        *successful += 1;
    }

    /// 增加失败调度数
    pub async fn increment_failed_schedulings(&self) {
        let mut failed = self.failed_schedulings.write().await;
        *failed += 1;
    }

    /// 记录调度时间
    pub async fn record_scheduling_time(&self, duration: Duration) {
        let mut times = self.scheduling_times.write().await;
        times.push(duration);

        // 限制样本数量，避免内存过度使用
        if times.len() > 10000 {
            times.drain(0..5000); // 移除前一半样本
        }
    }

    /// 记录池分配
    pub async fn record_pool_allocation(&self, pool_type: &str) {
        let mut allocations = self.pool_allocations.write().await;
        *allocations.entry(pool_type.to_string()).or_insert(0) += 1;
    }

    /// 记录优先级统计
    pub async fn record_priority_request(&self, priority: &str) {
        let mut stats = self.priority_stats.write().await;
        *stats.entry(priority.to_string()).or_insert(0) += 1;
    }

    /// 记录语言统计
    pub async fn record_language_request(&self, language: &str) {
        let mut stats = self.language_stats.write().await;
        *stats.entry(language.to_string()).or_insert(0) += 1;
    }

    /// 记录队列等待时间
    pub async fn record_queue_wait_time(&self, duration: Duration) {
        let mut times = self.queue_wait_times.write().await;
        times.push(duration);

        // 限制样本数量
        if times.len() > 10000 {
            times.drain(0..5000);
        }
    }

    /// 记录策略使用
    pub async fn record_policy_usage(
        &self,
        policy_name: &str,
        success: bool,
        decision_time: Duration,
        confidence: f64,
    ) {
        let mut usage = self.policy_usage.write().await;
        let stats = usage.entry(policy_name.to_string()).or_insert_with(PolicyUsageStats::default);
        
        stats.usage_count += 1;
        if success {
            stats.success_count += 1;
        }

        // 更新平均决策时间
        let total_decision_time = stats.avg_decision_time * stats.usage_count.saturating_sub(1) as u32 + decision_time;
        stats.avg_decision_time = total_decision_time / stats.usage_count as u32;

        // 记录置信度
        stats.confidence_distribution.push(confidence);
        if stats.confidence_distribution.len() > 1000 {
            stats.confidence_distribution.drain(0..500);
        }
    }

    /// 获取总请求数
    pub async fn get_total_requests(&self) -> u64 {
        *self.total_requests.read().await
    }

    /// 获取成功调度数
    pub async fn get_successful_schedulings(&self) -> u64 {
        *self.successful_schedulings.read().await
    }

    /// 获取失败调度数
    pub async fn get_failed_schedulings(&self) -> u64 {
        *self.failed_schedulings.read().await
    }

    /// 获取成功率
    pub async fn get_success_rate(&self) -> f64 {
        let total = self.get_total_requests().await;
        let successful = self.get_successful_schedulings().await;

        if total == 0 {
            0.0
        } else {
            successful as f64 / total as f64
        }
    }

    /// 获取平均调度时间
    pub async fn get_average_scheduling_time(&self) -> Duration {
        let times = self.scheduling_times.read().await;
        if times.is_empty() {
            Duration::from_millis(0)
        } else {
            let total: Duration = times.iter().sum();
            total / times.len() as u32
        }
    }

    /// 获取调度时间分位数
    pub async fn get_scheduling_time_percentile(&self, percentile: f64) -> Duration {
        let mut times = self.scheduling_times.read().await.clone();
        if times.is_empty() {
            return Duration::from_millis(0);
        }

        times.sort();
        let index = ((times.len() as f64 * percentile / 100.0) as usize).min(times.len() - 1);
        times[index]
    }

    /// 获取吞吐量
    pub async fn get_throughput(&self) -> f64 {
        let total_requests = self.get_total_requests().await;
        let uptime = self.start_time.elapsed();

        if uptime.as_secs() == 0 {
            0.0
        } else {
            total_requests as f64 / uptime.as_secs() as f64
        }
    }

    /// 获取指标快照
    pub async fn get_snapshot(&self) -> SchedulerMetricsSnapshot {
        let total_requests = self.get_total_requests().await;
        let successful_schedulings = self.get_successful_schedulings().await;
        let failed_schedulings = self.get_failed_schedulings().await;
        let success_rate = self.get_success_rate().await;
        let average_scheduling_time = self.get_average_scheduling_time().await;
        let median_scheduling_time = self.get_scheduling_time_percentile(50.0).await;
        let p99_scheduling_time = self.get_scheduling_time_percentile(99.0).await;
        let throughput = self.get_throughput().await;

        let pool_allocations = self.pool_allocations.read().await.clone();
        let priority_stats = self.priority_stats.read().await.clone();
        let language_stats = self.language_stats.read().await.clone();
        let policy_usage = self.policy_usage.read().await.clone();

        // 计算平均队列等待时间
        let queue_wait_times = self.queue_wait_times.read().await;
        let average_queue_wait_time = if queue_wait_times.is_empty() {
            Duration::from_millis(0)
        } else {
            let total: Duration = queue_wait_times.iter().sum();
            total / queue_wait_times.len() as u32
        };

        SchedulerMetricsSnapshot {
            total_requests,
            successful_schedulings,
            failed_schedulings,
            success_rate,
            average_scheduling_time,
            median_scheduling_time,
            p99_scheduling_time,
            pool_allocations,
            priority_stats,
            language_stats,
            average_queue_wait_time,
            policy_usage,
            uptime: self.start_time.elapsed(),
            throughput,
        }
    }

    /// 重置指标
    pub async fn reset(&self) {
        *self.total_requests.write().await = 0;
        *self.successful_schedulings.write().await = 0;
        *self.failed_schedulings.write().await = 0;
        self.scheduling_times.write().await.clear();
        self.pool_allocations.write().await.clear();
        self.priority_stats.write().await.clear();
        self.language_stats.write().await.clear();
        self.queue_wait_times.write().await.clear();
        self.policy_usage.write().await.clear();
        
        info!("调度器指标已重置");
    }

    /// 导出Prometheus格式指标
    pub async fn export_prometheus_metrics(&self) -> String {
        let snapshot = self.get_snapshot().await;
        let mut output = String::new();

        // 基础指标
        output.push_str(&format!(
            "# HELP scheduler_requests_total Total number of scheduling requests\n\
             # TYPE scheduler_requests_total counter\n\
             scheduler_requests_total {}\n\n",
            snapshot.total_requests
        ));

        output.push_str(&format!(
            "# HELP scheduler_successful_schedulings_total Total number of successful schedulings\n\
             # TYPE scheduler_successful_schedulings_total counter\n\
             scheduler_successful_schedulings_total {}\n\n",
            snapshot.successful_schedulings
        ));

        output.push_str(&format!(
            "# HELP scheduler_failed_schedulings_total Total number of failed schedulings\n\
             # TYPE scheduler_failed_schedulings_total counter\n\
             scheduler_failed_schedulings_total {}\n\n",
            snapshot.failed_schedulings
        ));

        output.push_str(&format!(
            "# HELP scheduler_success_rate Success rate of schedulings\n\
             # TYPE scheduler_success_rate gauge\n\
             scheduler_success_rate {:.4}\n\n",
            snapshot.success_rate
        ));

        output.push_str(&format!(
            "# HELP scheduler_scheduling_time_avg_seconds Average scheduling time\n\
             # TYPE scheduler_scheduling_time_avg_seconds gauge\n\
             scheduler_scheduling_time_avg_seconds {:.6}\n\n",
            snapshot.average_scheduling_time.as_secs_f64()
        ));

        output.push_str(&format!(
            "# HELP scheduler_scheduling_time_median_seconds Median scheduling time\n\
             # TYPE scheduler_scheduling_time_median_seconds gauge\n\
             scheduler_scheduling_time_median_seconds {:.6}\n\n",
            snapshot.median_scheduling_time.as_secs_f64()
        ));

        output.push_str(&format!(
            "# HELP scheduler_scheduling_time_p99_seconds 99th percentile scheduling time\n\
             # TYPE scheduler_scheduling_time_p99_seconds gauge\n\
             scheduler_scheduling_time_p99_seconds {:.6}\n\n",
            snapshot.p99_scheduling_time.as_secs_f64()
        ));

        output.push_str(&format!(
            "# HELP scheduler_throughput_requests_per_second Request throughput per second\n\
             # TYPE scheduler_throughput_requests_per_second gauge\n\
             scheduler_throughput_requests_per_second {:.2}\n\n",
            snapshot.throughput
        ));

        // 池分配统计
        for (pool_type, count) in &snapshot.pool_allocations {
            output.push_str(&format!(
                "# HELP scheduler_pool_allocations_total Total allocations per pool type\n\
                 # TYPE scheduler_pool_allocations_total counter\n\
                 scheduler_pool_allocations_total{{pool_type=\"{}\"}} {}\n\n",
                pool_type, count
            ));
        }

        // 优先级统计
        for (priority, count) in &snapshot.priority_stats {
            output.push_str(&format!(
                "# HELP scheduler_priority_requests_total Total requests per priority\n\
                 # TYPE scheduler_priority_requests_total counter\n\
                 scheduler_priority_requests_total{{priority=\"{}\"}} {}\n\n",
                priority, count
            ));
        }

        // 语言统计
        for (language, count) in &snapshot.language_stats {
            output.push_str(&format!(
                "# HELP scheduler_language_requests_total Total requests per language\n\
                 # TYPE scheduler_language_requests_total counter\n\
                 scheduler_language_requests_total{{language=\"{}\"}} {}\n\n",
                language, count
            ));
        }

        // 策略使用统计
        for (policy, stats) in &snapshot.policy_usage {
            output.push_str(&format!(
                "# HELP scheduler_policy_usage_total Total policy usage count\n\
                 # TYPE scheduler_policy_usage_total counter\n\
                 scheduler_policy_usage_total{{policy=\"{}\"}} {}\n\n",
                policy, stats.usage_count
            ));

            let success_rate = if stats.usage_count > 0 {
                stats.success_count as f64 / stats.usage_count as f64
            } else {
                0.0
            };

            output.push_str(&format!(
                "# HELP scheduler_policy_success_rate Policy success rate\n\
                 # TYPE scheduler_policy_success_rate gauge\n\
                 scheduler_policy_success_rate{{policy=\"{}\"}} {:.4}\n\n",
                policy, success_rate
            ));

            output.push_str(&format!(
                "# HELP scheduler_policy_decision_time_avg_seconds Average policy decision time\n\
                 # TYPE scheduler_policy_decision_time_avg_seconds gauge\n\
                 scheduler_policy_decision_time_avg_seconds{{policy=\"{}\"}} {:.6}\n\n",
                policy, stats.avg_decision_time.as_secs_f64()
            ));
        }

        output
    }
}

impl Default for SchedulerMetrics {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_metrics_basic_operations() {
        let metrics = SchedulerMetrics::new();

        // 测试基础计数
        metrics.increment_submitted_requests().await;
        metrics.increment_submitted_requests().await;
        metrics.increment_successful_schedulings().await;

        assert_eq!(metrics.get_total_requests().await, 2);
        assert_eq!(metrics.get_successful_schedulings().await, 1);
        assert_eq!(metrics.get_success_rate().await, 0.5);
    }

    #[tokio::test]
    async fn test_scheduling_time_recording() {
        let metrics = SchedulerMetrics::new();

        metrics.record_scheduling_time(Duration::from_millis(100)).await;
        metrics.record_scheduling_time(Duration::from_millis(200)).await;

        let avg_time = metrics.get_average_scheduling_time().await;
        assert_eq!(avg_time, Duration::from_millis(150));

        let median_time = metrics.get_scheduling_time_percentile(50.0).await;
        assert!(median_time >= Duration::from_millis(100) && median_time <= Duration::from_millis(200));
    }

    #[tokio::test]
    async fn test_pool_allocation_tracking() {
        let metrics = SchedulerMetrics::new();

        metrics.record_pool_allocation("hot").await;
        metrics.record_pool_allocation("warm").await;
        metrics.record_pool_allocation("hot").await;

        let snapshot = metrics.get_snapshot().await;
        assert_eq!(snapshot.pool_allocations.get("hot"), Some(&2));
        assert_eq!(snapshot.pool_allocations.get("warm"), Some(&1));
    }

    #[tokio::test]
    async fn test_policy_usage_tracking() {
        let metrics = SchedulerMetrics::new();

        metrics.record_policy_usage(
            "resource_aware",
            true,
            Duration::from_millis(10),
            0.8,
        ).await;
        
        metrics.record_policy_usage(
            "resource_aware",
            false,
            Duration::from_millis(20),
            0.6,
        ).await;

        let snapshot = metrics.get_snapshot().await;
        let stats = snapshot.policy_usage.get("resource_aware").unwrap();
        
        assert_eq!(stats.usage_count, 2);
        assert_eq!(stats.success_count, 1);
        assert_eq!(stats.avg_decision_time, Duration::from_millis(15));
        assert_eq!(stats.confidence_distribution.len(), 2);
    }

    #[tokio::test]
    async fn test_metrics_snapshot() {
        let metrics = SchedulerMetrics::new();

        // 添加测试数据
        metrics.increment_submitted_requests().await;
        metrics.increment_successful_schedulings().await;
        metrics.record_scheduling_time(Duration::from_millis(50)).await;
        metrics.record_pool_allocation("hot").await;
        metrics.record_priority_request("high").await;
        metrics.record_language_request("python").await;

        let snapshot = metrics.get_snapshot().await;

        assert_eq!(snapshot.total_requests, 1);
        assert_eq!(snapshot.successful_schedulings, 1);
        assert_eq!(snapshot.success_rate, 1.0);
        assert!(!snapshot.pool_allocations.is_empty());
        assert!(!snapshot.priority_stats.is_empty());
        assert!(!snapshot.language_stats.is_empty());
    }

    #[tokio::test]
    async fn test_metrics_reset() {
        let metrics = SchedulerMetrics::new();

        // 添加数据
        metrics.increment_submitted_requests().await;
        metrics.increment_successful_schedulings().await;

        assert_eq!(metrics.get_total_requests().await, 1);

        // 重置
        metrics.reset().await;

        assert_eq!(metrics.get_total_requests().await, 0);
        assert_eq!(metrics.get_successful_schedulings().await, 0);
    }
}